﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tools.Base;

namespace Tools.EventObjectMoudle
{
    internal class EventSource
    {
        public void registerListener(int eventType, IEventListener listener)
        {
            lock (this.listeners)
            {
                List<IEventListener> listenerList = null;
                if (!this.listeners.TryGetValue(eventType, out listenerList))
                {
                    listenerList = new List<IEventListener>();
                    this.listeners.Add(eventType, listenerList);
                }
                listenerList.Add(listener);
            }
        }

        public void removeListener(int eventType, IEventListener listener)
        {
            lock (this.listeners)
            {
                List<IEventListener> listenerList = null;
                if (this.listeners.TryGetValue(eventType, out listenerList))
                {
                    listenerList.Remove(listener);
                }
            }
        }

        public void fireEvent(EventObject eventObj)
        {
            if (eventObj != null && eventObj.getEventType() != -1)
            {
                List<IEventListener> copylistenerList = this._getEventListener(eventObj.getEventType());
                if (copylistenerList != null)
                {
                    this.dispatchEvent(eventObj, copylistenerList);
                }
            }
        }

        private List<IEventListener> _getEventListener(int eventType)
        {
            List<IEventListener> result;
            lock (this.listeners)
            {
                List<IEventListener> listenerList = null;
                if (!this.listeners.TryGetValue(eventType, out listenerList))
                {
                    result = null;
                }
                else
                {
                    List<IEventListener> copylistenerList = listenerList.GetRange(0, listenerList.Count);
                    result = copylistenerList;
                }
            }
            return result;
        }

        private void dispatchEvent(EventObject eventObj, List<IEventListener> listenerList)
        {
            int i = 0;
            while (listenerList != null && i < listenerList.Count)
            {
                try
                {
                    if (!eventObj.TriggerNext)
                    {
                        break;
                    }
                    listenerList[i].processEvent(eventObj);
                }
                catch (Exception ex)
                {
                    LogManager.WriteLog(string.Format("事件处理错误: {0},{1}", eventObj.getEventType(), ex), null, true);
                }
                i++;
            }
        }

        private Dictionary<int, List<IEventListener>> listeners = new Dictionary<int, List<IEventListener>>();
    }

    public class GlobalEventSource
    {
        private GlobalEventSource()
        {
        }

        public static GlobalEventSource getInstance()
        {
            return GlobalEventSource.instance;
        }

        public void registerListener(int eventType, IEventListener listener)
        {
            this._es.registerListener(eventType, listener);
        }

        public void removeListener(int eventType, IEventListener listener)
        {
            this._es.removeListener(eventType, listener);
        }

        public EventObject fireEvent(int eventType, params object[] args)
        {
            return this.fireEvent(new EventObject(eventType, args));
        }

        public EventObject fireEvent(EventObject eventObj)
        {
            this._es.fireEvent(eventObj);
            return eventObj;
        }

        private static GlobalEventSource instance = new GlobalEventSource();

        private EventSource _es = new EventSource();
    }
}
